import React from "react";
import {DndProvider, DragSource, DropTarget} from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';

import './grid.scss';
import BaseComponent from "../BaseComponent";
import Grid from "./Grid";
import ResizeGrid from "./ResizeGrid";

let dragingIndex = -1;

class BodyRow extends React.Component {
    render() {
        const {isOver, connectDragSource, connectDropTarget, onRowMove, ...restProps} = this.props;
        const style = {...restProps.style, cursor: 'move'};

        let {className} = restProps;
        if (isOver) {
            if (restProps.index > dragingIndex) {
                className += ' drop-over-downward';
            }
            if (restProps.index < dragingIndex) {
                className += ' drop-over-upward';
            }
        }

        return connectDragSource(
            connectDropTarget(<tr {...restProps} className={className} style={style}/>),
        );
    }
}

const rowSource = {
    beginDrag(props) {
        return {
            record: props.children[0].props.record
        };
    },
};

const rowTarget = {
    drop(props, monitor) {

        const dragRecord = monitor.getItem().record;
        const hoverRecord = props.children[0].props.record;

        // Don't replace items with themselves
        if (dragRecord === hoverRecord) {
            return;
        }

        // Time to actually perform the action
        props.onRowMove(dragRecord, hoverRecord);

        // Note: we're mutating the monitor item here!
        // Generally it's better to avoid mutations,
        // but it's good here for the sake of performance
        // to avoid expensive index searches.
        // monitor.getItem().index = hoverIndex;
    },
};

const DragableBodyRow = DropTarget('row', rowTarget, (connect, monitor) => ({
    connectDropTarget: connect.dropTarget(),
    isOver: monitor.isOver(),
}))(
    DragSource('row', rowSource, connect => ({
        connectDragSource: connect.dragSource(),
    }))(BodyRow),
);

export default class DndGrid extends BaseComponent {

    static defaultProps = {
        _resizeable: false,
        _initLoading: true,//是否初始化显示加载提示
        _onInitLoading: undefined,//初始化加载函数
        _showPage: true,//是否显示分页
        _pageSize: 20,//默认pageSize大小
        _onPageChange: undefined,//分页改变
        dataSource: [],//[] 或 {curPage: 1, pageSize: 20, totalCount: 0, result: []},
        bordered: true,
        _onRowClick: undefined,//({record, index, event})=>{}
        _onRowDoubleClick: undefined,//({record, index, event})=>{}
        _onRowContextMenu: undefined,//({record, index, event})=>{}
        _onRowMouseEnter: undefined,//({record, index, event})=>{}
        _onRowMouseLeave: undefined,//({record, index, event})=>{}
        _onRowMove: undefined//({dragRecord, dragIndex, hoverRecord, hoverIndex})=>{}
    };

    components = {
        body: {
            row: DragableBodyRow,
        },
    };

    closeLoadingIndicator() {
        this.grid.closeLoadingIndicator();
    }

    showLoadingIndicator(text = '加载中...') {
        this.grid.showLoadingIndicator(text);
    }

    getCurPage() {
        return this.grid.getCurPage();
    }

    setData(data, {curPage, pageSize, totalCount} = {}) {
        this.grid.setData(data, {curPage, pageSize, totalCount});
    }

    getData() {
        return this.grid.getData();
    }

    getDataAt(index) {
        return this.grid.getDataAt(index);
    }

    render() {
        let className = this.props.className;
        if (className) {
            className = `${className} dnd-grid`;
        } else {
            className = 'dnd-grid';
        }

        let onRow = this.props.onRow;
        if (!onRow) {
            onRow = (record, index) => {
                return {
                    index,
                    onClick: event => {
                        if (this.props._onRowClick) {
                            this.props._onRowClick({record, index, event});
                        }
                    },
                    onDoubleClick: event => {
                        if (this.props._onRowDoubleClick) {
                            this.props._onRowDoubleClick({record, index, event});
                        }
                    },
                    onContextMenu: event => {
                        if (this.props._onRowContextMenu) {
                            this.props._onRowContextMenu({record, index, event});
                        }
                    },
                    onMouseEnter: event => {
                        if (this.props._onRowMouseEnter) {
                            this.props._onRowMouseEnter({record, index, event});
                        }
                    },
                    onMouseLeave: event => {
                        if (this.props._onRowMouseLeave) {
                            this.props._onRowMouseLeave({record, index, event});
                        }
                    },
                    onRowMove: (dragRecord, hoverRecord) => {
                        if (this.props._onRowMove) {
                            this.props._onRowMove(dragRecord, hoverRecord);
                        }
                    }
                }
            }
        }
        return (
            <DndProvider backend={HTML5Backend}>
                {
                    this.props._resizeable ? (
                        <ResizeGrid
                            {...this.props}
                            className={className}
                            ref={(o) => this.grid = o}
                            components={this.components}
                            onRow={onRow}
                        />
                    ) : (
                        <Grid
                            {...this.props}
                            className={className}
                            ref={(o) => this.grid = o}
                            components={this.components}
                            onRow={onRow}
                        />
                    )
                }
            </DndProvider>
        );
    }
}
